#-*- coding:utf-8 -*-

import threading as td
import socket as line
from flask import *
import time
import ast
import os

__verson__ = '1.9.4'

def To_IP(domain):
    addr = line.getaddrinfo(domain, 'http')
    return addr[0][4][0]

def Host_IP():
    try:
        s = line.socket(line.AF_INET, line.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    except OSError:
        ip = '127.0.0.1'
    finally:
        s.close()
    return ip

class Net:
    contin = True

    def __init__(self, port):
        self.__terminal_t = []
        self.hostname = line.gethostname()
        self.terminal = []
        self.__port = port
        self.__UDP = td.Thread(target=self.__UDP_find)
        self.__UDP.start()
        self.__ats = td.Timer(0, self.__AutomaticSearch)
        self.__ats.start()
    
    def Setting(self, target, content):
        if target == "ats":
            if content == True:
                self.__ats.start()
            else:
                try:
                    self.__ats.cancel()
                except:
                    pass
        elif target == 'hostname':
            self.hostname = content
            self.terminal = []
        elif target == 'port':
            self.__port = int(content)

    def GetInfo(self):
        dat = {
            "name":self.hostname,
            "ip":Host_IP(),
            "port":self.__port,
            "verson":__verson__,
        }
        return str(dat)

    def __UDP_find(self):
        network = '<broadcast>'
        sch_s = line.socket(line.AF_INET, line.SOCK_DGRAM)
        sch_s.setsockopt(line.SOL_SOCKET, line.SO_BROADCAST, 1)
        sch_s.bind(('', 10305))
        sch_l = line.socket(line.AF_INET, line.SOCK_DGRAM)
        sch_l.setsockopt(line.SOL_SOCKET, line.SO_BROADCAST, 1)
        while self.contin:
            try:data, addr = sch_s.recvfrom(1024)
            except:continue
            data = data.decode("utf-8")
            if not Host_IP() in addr[0]:
                if data == "search":
                    addr = (addr[0], 10305)
                    sch_l.sendto(self.GetInfo().encode("utf-8"), (network, 10305))
                if "ip" in data and "port" in data:
                    try:
                        dat = ast.literal_eval(data)
                        self.__terminal_t.append(dat)
                    except:
                        pass
    
    def Search(self, Timeouts=5):
        self.__terminal_t = []
        s = line.socket(line.AF_INET, line.SOCK_DGRAM)
        s.setsockopt(line.SOL_SOCKET, line.SO_BROADCAST, 1)
        network = '<broadcast>'
        s.sendto("search".encode("utf-8"), (network, 10305))
        time.sleep(Timeouts)
        return self.__terminal_t
    
    def SearchUpper(self, Times=1, While=2):
        data = []
        N = 1
        while N <= While:
            N = N + 1
            i = self.Search(Times)
            if i != []:
                for o in i:
                    if not o in data:
                        data.append(o)
        self.terminal = data

    def __AutomaticSearch(self):
        self.SearchUpper()
        self.__ats = td.Timer(0, self.__AutomaticSearch)
        self.__ats.start()

app = Flask(__name__)
n = Net(10306)

@app.route("/net/")
@app.route("/net/<command>/")
@app.route("/net/<command>/<target>/")
def net(command='', target=line.gethostname()):
    ip = request.remote_addr
    if ip != '127.0.0.1':
        if ip != Host_IP():
            return 'IP Error'
    if command == '':
        return 'command Error'
    if command == 'terminal':
        return str(n.terminal)
    elif command == 'info':
        return str(n.GetInfo())
    elif command == 'name':
        n.Setting('hostname', str(target))
        return str(n.GetInfo())
        

@app.route('/module/<req>/')
@app.route('/module/<req>/<target>/')
def module(req='', target=''):
    ip = request.remote_addr
    if ip != '127.0.0.1':
        if ip != Host_IP():
            return 'IP Error'
    if req == 'port':
        n.Setting('port', int(target))
        return str(n.GetInfo())

@app.route("/info/<req>/")
def req(req=''):
    if req != '':
        pass
    else:
        return 'req Error'

@app.route("/hi/")
def hi():
    ip = request.remote_addr
    print(str(ip))
    return str(ip)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=10305)